package org.tri.entity;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.hibernate.annotations.Cascade;
import org.tri.gui.worker.TransientListener;
import org.tri.gui.worker.TransientWorker;

/**
 * La clase {@code Compra} almacena los datos pertinentes a una compra, 
 * incluyendo los animales que se adquirieron en la misma
 * @author Lucas Giacomazzi
 * @version 1.0, Nov 16, 2011
 */
@Entity
@Table ( name = "compra" )
public class Compra extends AbstractCompra 
                    implements TransientListener{

    /** Listado de animales que todavia se consideran actuales. */
    private List<Animal> animales = new ArrayList<Animal>();
    /** Listado de animales considerados históricos. */
    private List<AnimalHistorico> animalesHistoricos;

    /**
     * Constructor sin parámetros utilizado por hibernate.
     */
    public Compra() {
        super();
        
    }//end constructor
    
    /**
     * Crea una compra indicando el establecimiento en el que se 
     * realizo.
     * @param establecimiento establecimiento en que seralizo la compra.
     */
    public Compra( Establecimiento establecimiento ) {
        super();
        setEstablecimiento( establecimiento );
        
    }//end constructor    
        
    /**
     * Nos devuelve los animales asociados a una compra
     * @return List<Animal> lista con los animales asociadas a la compra
     */
    @OneToMany ( cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH },
                 mappedBy = "compra" )
    @Cascade ( { org.hibernate.annotations.CascadeType.SAVE_UPDATE,
                 org.hibernate.annotations.CascadeType.EVICT } )
    public List<Animal> getAnimales() {
        return animales;

    }//end método getAnimales 

    /**
     * Nos permite cambiar la lista actual de animales asociadas a 
     * la compra por una lista nueva. Este método es utilizado exclusivamente
     * por Hibernate para recuperar los animales correspondientes a la compra
     * desde la base de datos.
     * @param caravanas List<Animal> lista de animales asociados a la compra
     */
    protected void setAnimales( List<Animal> caravanas ) {
        this.animales = caravanas;

    }//end método setAnimales

    /**
     * Nos devuelve los animales asociados a una compra
     * @return List<AnimalHistorico> lista con los animales historicos asociadas
     * a la compra
     */
    @OneToMany ( cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH },
                 mappedBy = "compra" )
    @Cascade ( { org.hibernate.annotations.CascadeType.SAVE_UPDATE,
                 org.hibernate.annotations.CascadeType.EVICT } )
    public List<AnimalHistorico> getAnimalesHistoricos() {
        return animalesHistoricos;

    }//end método getAnimalesHistoricos

    /**
     * Nos permite cambiar la lista actual de animales histŕocias asociadas a 
     * la compra por una lista nueva. Este método es utilizado exclusivamente
     * por Hibernate para recuperar los animales correspondientes a la compra
     * desde la base de datos.
     * @param caravanas List<AnimalHistorico> lista de animales historicos
     * asociados a la compra
     */
    protected void setAnimalesHistoricos( List<AnimalHistorico> animalesHistoricos ) {
        this.animalesHistoricos = animalesHistoricos;

    }//end método setAnimalesHistoricos

    /**
     * {@inheritDoc} 
     */
    @Override
    public List<AbstractAnimal> obtenerAnimales() {
        List<AbstractAnimal> anim = new ArrayList<AbstractAnimal>();

        anim.addAll( getAnimales() );
        anim.addAll( getAnimalesHistoricos() );

        return anim;

    }//end método obtenerAnimales

    /**
     * Nos permite asociar un animal a la compra
     * @param caravana número de carvana
     */
    @Override
    public void agregarAnimal( String caravana ) {
        //creamos el animal
        Animal animal = new Animal( caravana, this );

        //agregamos el animal a las compras
        this.getAnimales().add( animal );
        
        this.setCantidadAnimales( getAnimales().size() );

    }//end método agregarAnimal

    /**
     * Nos permite asociar una lista de animales a la compra. 
     * Puede que este método sea cambiado de clase. Don't use it!! =(
     * @param caravanas lista de caravanas a agregar
     */
    @Override
    public void agregarAnimales( List<String> caravanas ) {
        for ( String c : caravanas )
            agregarAnimal( c );

    }//end método agregarAnimales
    
    @Override
    public void eliminarAnimal(Animal animal) {
        this.animales.remove(animal);
        
        //elimino el animal de la base de datos
        TransientWorker worker = new TransientWorker( animal );
        
        worker.addTransientListener( this );
        
        worker.execute();
        
        this.setCantidadAnimales( getAnimales().size() );
        
    }

    @Override
    public void eliminarAnimales(List<Animal> animales) {
        for(Animal a: animales){
            eliminarAnimal(a);
            
        }
                
    }

    @Override
    public void doneTransit() {
        
    }

    @Override
    public void errorTransit(ExecutionException ex) {
        
    }

}//end clase Compra

